贪心算法之单源最短路径

问题:在一个有向网络中,从某点出发得到所有到该顶点的最短距离。


迪杰斯特拉算法是解单源最短路径问题的一个贪心算法,其基本思想是,设置顶点集合S不断的贪心选择来扩充这个集合。当源点到该顶点的最短距离已知,则添加到集合来,最终包括网络中的所有顶点。


贪心选择:

step1:首先选择网络中的某一顶点V出发,那么该顶点肯定可以添加到S中,然后以V为源点,得到它到其他顶点的距离(初始化d[],表示V到其他顶点的距离)

step2:在这些顶点中选择没有标记过的(即未添加到S集合中的点)  并且到V的距离最小的顶点V’,然后将其标记

step3:更新d[],从V'出发遍历网络没有标记的顶点,如果找到一个点d[u]+edge[u][j]<d[j]的情况,则更新d[j]=d[u]+edge[u][j]

step4:重复step2


性能分析:

      算法时间主要花在两个for循环中,时间复杂度为O(n2)


代码实现:


#include<stdio.h>

typedef char VertexType;
typedef int EdgeType;
#define MAX 20//定义数组大小
#define INFINITY 500

typedef struct 
{
	VertexType vexs[MAX];
	EdgeType edges[MAX][MAX];
	int vexnum;//记录图的顶点数
	int arcnum;//记录图的边或弧的条数
}AdjMatrix;
//创建图的邻接矩阵
AdjMatrix CreatGraph_Matrix(int graphtype)
{
	AdjMatrix G;
	int i,j,k;
	int weight;
	printf("please input graph's vexnum and arcnum:\n");
	scanf("%d,%d",&G.vexnum,&G.arcnum);
    setbuf(stdin,NULL);
	for(i=1;i<=G.vexnum;i++)
	{
		scanf("%c",&G.vexs[i]);
		 setbuf(stdin,NULL);
	}
	setbuf(stdin,NULL);
	
	for(i=1;i<=G.vexnum;i++)
		for(j=1;j<=G.vexnum;j++)
			G.edges[i][j]=INFINITY;
	for(k=1;k<=G.arcnum;k++)
	{
		printf("please input NO.%d edge's start,end and weight:\n",k);
		scanf("%d,%d,%d",&i,&j,&weight);
		G.edges[i][j]=weight;
	}
	
	return G;
}



void Dijkstra(AdjMatrix &N,int v,int D[],int P[])
{
	int S[MAX];
	int mindistance,temp;
	int i,j,u;
	/*******开始初始化的工作*******/
	for(i=1;i<=N.vexnum;i++)//前提是采取邻接矩阵储存,并且是有向网络
	{
		D[i]=N.edges[v][i];
		S[i]=0;
		if(INFINITY==N.edges[v][i])
			P[i]=-1;
		else
			P[i]=v;
	}

	S[v]=1;
	/**********开始最短路径求解************/
	for(i=1;i<=N.vexnum;i++)
	{
		mindistance=INFINITY;
		//在D中找出尚未确定最短路径的顶点中路径长度最小的顶点u
		for(j=1;j<=N.vexnum;j++)
		{
			if(0==S[j]&&D[j]<mindistance)
			{
				mindistance=D[j];
				u=j;
			}
		}
		S[u]=1;//找到路径最小的顶点,然后进行标识

		//对还未确定最短路径的顶点进行调整
		for(j=1;j<=N.vexnum;j++)
		{
			if(0==S[j])//未确定最短路径的顶点
			{
				temp=D[u]+N.edges[u][j];
			    if(D[j]>temp)
				{
					D[j]=temp;//修改最短路径
				    P[j]=u;//同时修改前驱
				}
			}
		}
	
	}
}
int main()
{
	AdjMatrix G;
	G=CreatGraph_Matrix(51);
    int D[MAX],P[MAX];
	Dijkstra(G,1,D,P);
    for(int i=1;i<=G.vexnum;i++)
	{
		printf("D[%d]=%d,P[%d]=%d\n",i,D[i],i,P[i]);
	}
	return 0;
}



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值